package day16;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * @author: 王丹
 * @create: 2021-07-23 14:36
 **/
public class Demo4 {

    /**
     * 代码中，t1、t2、t3启动之后，都阻塞在 commanderCd.await();，主线程模拟发枪准备操作耗时5秒，然后调用
     * commanderCd.countDown();模拟发枪操作，此方法被调用以后，阻塞在 commanderCd.await();的3个线程会向下执行。
     * 主线程调用 countDownLatch.await();之后进行等待，每个人跑完之后，调用 countDown.countDown();通知一下
     * countDownLatch让计数器减1，最后3个人都跑完了，主线程从 countDownLatch.await();返回继续向下执行。
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName() + "线程 start!");
        CountDownLatch commanderCd = new CountDownLatch(1);
        CountDownLatch countDown = new CountDownLatch(3);
        long starTime = System.currentTimeMillis();
        T t1 = new T("小李", 2, commanderCd, countDown);
        t1.start();
        T t2 = new T("嚣张", 5, commanderCd, countDown);
        t2.start();
        T t3 = new T("小王", 10, commanderCd, countDown);
        t3.start();
        //主线程休眠5秒，模拟指令员准备发枪时间
        TimeUnit.SECONDS.sleep(5);

        System.out.println(System.currentTimeMillis() + ",枪响了，大家开始跑！");
        commanderCd.countDown();
        countDown.await();
        long endTime = System.currentTimeMillis();
        System.out.println(System.currentTimeMillis() + "," + Thread.currentThread().getName() + " 所有人跑完了，主线程耗时：" + (endTime-starTime));
    }

    public static class T extends Thread {
        int runCostSeconds;
        CountDownLatch commanderCd;
        CountDownLatch countDown;

        public T(String name, int runCostSeconds, CountDownLatch commanderCd, CountDownLatch countDown) {
            super(name);
            this.runCostSeconds = runCostSeconds;
            this.commanderCd = commanderCd;
            this.countDown = countDown;
        }

        public void run() {
            //等待指令员枪响
            try {
                commanderCd.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Thread ct = Thread.currentThread();
            long startTime = System.currentTimeMillis();
            System.out.println(startTime + "," + ct.getName() + ",开始跑!");
            try {
                TimeUnit.SECONDS.sleep((long) this.runCostSeconds);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                countDown.countDown();
            }
            long endTime = System.currentTimeMillis();
            System.out.println(endTime + "," + ct.getName() + ",跑步结束,耗时:" + (endTime - startTime));
        }
    }
}
